#include "tableinfomodle.h"


struct TableInfoModlePrivate {
    QVector<QVariantMap> data;//具体数据
    QStringList header; //头数据
    QMap<QString, bool> selectInfos;//当前选中的数据
    bool isCanSelected = false;
    bool multipleChoice = false;
};


TableInfoModel::TableInfoModel(const QStringList &header, QObject *parent)
    : QAbstractItemModel{parent}
{
    m_d = new TableInfoModlePrivate();
    m_d->header = header;
}

void TableInfoModel::setCanSelected(bool canSelected)
{
    m_d->isCanSelected = canSelected;
}

QVariant TableInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    //Q_ASSERT(m_d->header.size() <=  section);
    if (role == Qt::DisplayRole) {
        if (orientation == Qt::Horizontal) {
            if (m_d->isCanSelected) {
                if (section == 0) return "";
                section -= 1;
            }
            return m_d->header.at(section); // 返回列标题
        }
    }
    return QVariant();
}

QModelIndex TableInfoModel::index(int row, int column, const QModelIndex &parent) const
{
    if (row >= 0)
        return createIndex(row, column);
    return QModelIndex();
}

QModelIndex TableInfoModel::parent(const QModelIndex &index) const
{
    // FIXME: Implement me!
    return QModelIndex(); // 根节点没有父节点
}

int TableInfoModel::rowCount(const QModelIndex &parent) const
{
    return m_d->data.size();
}

int TableInfoModel::columnCount(const QModelIndex &parent) const
{
    auto size = m_d->header.size();
    if (m_d->isCanSelected) size += 1;
    return size;
}

QVariant TableInfoModel::data(const QModelIndex &index, int role) const
{
    auto row = index.row();
    auto col = index.column();
    if (row >= m_d->data.size())
        return QVariant();
    const auto& info =  m_d->data[row];
    if (role == Qt::DisplayRole && index.isValid()) {
        if (m_d->isCanSelected) {
            if (col == 0) return QVariant();
            col -= 1;
        }
        const auto& key = m_d->header.at(col);
        return info[key];
    }

    if (role == Qt::CheckStateRole && index.column() == 0 && m_d->isCanSelected) {
        const QVariantMap& item = m_d->data[row];
        const auto& name = item["Name"].toString();
        bool isChecked = m_d->selectInfos[name];
        return isChecked ? Qt::Checked : Qt::Unchecked;
    }

    return QVariant();
}

bool TableInfoModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    auto col = index.column();
    if (role == Qt::EditRole && index.isValid()) {
        if (m_d->isCanSelected) {
            if (col == 0) return true;
            col -= 1;
        }
        auto& info =m_d->data[index.row()];
        const auto& key = m_d->header.at(col);
        info[key] = value;
        emit dataChanged(index, index); // 发出数据变化信号
        return true;
    } else if (m_d->isCanSelected && role == Qt::CheckStateRole && col == 0) {
        QVector<QVariantMap>& data = const_cast<QVector<QVariantMap>&>(infoData());
        QVariantMap& item = data[index.row()];
        auto name = item["Name"].toString();
        auto& flag = m_d->selectInfos[name];
        flag = !flag;
        if (!m_d->multipleChoice && flag) {
            for (const auto& key : m_d->selectInfos.keys()) {
                if (name == key) continue;
                auto& f = m_d->selectInfos[key];
                f = false;
            }
        }

        QModelIndex topLeft = this->index(0, 0);  // 第一行第一列
        QModelIndex bottomRight = this->index(rowCount() - 1, 0);  // 最后一行第一列
        emit dataChanged(topLeft, bottomRight, {role});
        // emit dataChanged(index, index, {role});
        return true;
    }
    return false;
}

Qt::ItemFlags TableInfoModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
    if (m_d->isCanSelected && index.column() == 0) {
        return defaultFlags | Qt::ItemIsUserCheckable;
    }
    return defaultFlags;
}

void TableInfoModel::updateInfo(const QVector<QVariantMap> &data)
{
    beginResetModel();
    m_d->data = data;
    m_d->selectInfos.clear();
    if (m_d->isCanSelected) {
        for (const auto& dt : m_d->data) {
            auto key = dt["Name"].toString();
            m_d->selectInfos[key] = false;
        }
    }
    endResetModel();
}

const QVector<QVariantMap> &TableInfoModel::infoData()
{
    return m_d->data;
}

const QStringList TableInfoModel::selectInfos()
{
    QStringList info;
    for (auto it = m_d->selectInfos.begin(); it != m_d->selectInfos.end(); ++it) {
        if (it.value()) info.append(it.key());
    }
    return info;
}

void TableInfoModel::setSelectInfos(const QStringList &selectInfos)
{
    beginResetModel();
    for (const auto& key : selectInfos)
        m_d->selectInfos[key] = true;
    endResetModel();
}

void TableInfoModel::setMultipleChoice()
{
    m_d->multipleChoice = true;
}

